All these configuration options can
also be done very easily with SQL Server Management Studio. The
following sections occasionally describe that capability but focus on
the SQL commands method because you will usually use this method in
real-life production systems.
sp_addlinkedserver
Before you can access an
external data source through SQL Server, it must be registered inside
the database as a linked server. Essentially, you must capture
(register) the connection information and specific data source
information within SQL Server. After it is registered, the data source
can simply be referenced within the SQL statement by a single logical
name. You use the sp_addlinkedserver
stored procedure for this registering purpose. Only users with the
sysadmin or setupadmin fixed server roles can run this procedure.
SQL Server 2008 ships with a
number of OLE DB providers, including providers for Oracle, DB2,
Informix, Access, and other SQL Server 6.5/7.0/2000/2005 databases, as
well as databases that can be reached through ODBC and JDBC. SQL Server
also comes with OLE DB providers for Microsoft Excel spreadsheets and
Indexing Service and a whole bunch more. Microsoft puts each of these
providers through extensive testing to certify them. We have found that
sometimes a provider isn’t available on the 64-bit version of SQL
Server 2008 yet. So, as a precaution, check the list of 64-bit
providers before
you upgrade your SQL Server to the 2008 64-bit version. If you are not
using a Microsoft-certified provider, however, you might still be able
to use that provider if it is compliant with the OLE DB provider
specifications.
Tip
When a linked server is created using sp_addlinkedserver,
a default self-mapping is added for all local logins. This means that
for non–SQL Server providers, SQL Server authenticated logins may be
able to gain access to the provider under the SQL Server service
account. If you want, you can issue the sp_droplinkedsrvlogin command to remove these mappings.
Figure 1
depicts the overall technical architecture of what is being enabled via
linked servers and providers. There is a SQL Server 2008 side set of
provider DLLs, along with a client-side provider that communicates
directly with the data sources. Clients usually connect to SQL Server
2008 via the native SQLNCLI provider (OLE DB) or via the ODBC provider.
This provider
architecture allows data sources to be accessed from within SQL Server
2005 with the highest degree of efficiency and integrity possible.
Some of the arguments for sp_addlinkedserver
are needed only for certain OLE DB providers. Because of the number of
different options and settings available, you should always
double-check the documentation for the OLE DB provider to determine
exactly which arguments must be provided and what strings are to be
specified. Following is the sp_addlinkedserver procedure:
sp_addlinkedserver [@server =] 'server'
[, [@srvproduct =] 'product_name']
[, [@provider =] 'provider_name']
[, [@datasrc =] 'data_source']
[, [@location =] 'location']
[, [@provstr =] 'provider_string']
[, [@catalog =] 'catalog']
Following are the elements of this syntax:
server— The name of the linked server that will be added (@server parameter).
product_name— The product name of the OLE DB provider (@srvproduct parameter). If this argument is set to 'SQL Server', only the @server argument is required. For all other OLE DB providers delivered with SQL Server, you can ignore this parameter.
provider_name— The unique programmatic identifier (PROGID). This value must match the PROGID in the Registry for the particular OLE DB provider (@provider parameter). The following are the OLE DB providers delivered with SQL Server and the corresponding values for the provider_name argument:
OLE DB Provider | Value (PROGID) |
---|
SQL Server | SQLNCLI (OLE DB provider) |
SQL Server | SQLOLEDB |
Access DB/Jet | Microsoft.Jet.OLEDB.4.0 (32-bit only) |
Excel spreadsheets | Microsoft.Jet.OLEDB.4.0 (32-bit only) |
ODBC | MSDASQL |
DB2 | DB2OLEDB |
Oracle | MSDAORA (32-bit only) |
Oracle, Version 8 or later | OraOLEDB.Oracle (32-bit only) |
File system | MSIDXS (through Indexing Service) |
data_source— A data source that points to the particular version of the OLE DB source (@datasrc
parameter). For example, for setting up an Access linked server, this
argument holds the path to the file. For setting up a SQL Server linked
server, this argument holds the machine name of the linked SQL Server.
Following are the OLE DB providers delivered with SQL Server and the
corresponding values for this argument:
OLE DB Provider | Value |
---|
SQL Server | Network name of the SQL Server |
Access DB/Jet | Full pathname to the file |
Excel spreadsheet | Full pathname to spreadsheets |
ODBC | System DSN or ODBC connection string |
Oracle | SQL*Net alias |
Oracle, Version 8 or later | Alias for the database |
DB2 | Catalog name of the database |
File System | Indexing Service catalog name (Indexing Service) |
location— The location string, possibly used by the OLE DB provider (@location parameter).
provider_string— The connection string, possibly used by the OLE DB provider (@provstr parameter).
catalog— The catalog string, possibly used by the OLE DB provider (@catalog parameter).
The SQLNCLI native SQL provider uses the same OLE DB provider code, so it is considered the same provider as SQLOLEDB.
There are also many other “certified” providers, such as an Analysis
Services data mining model provider, an Analysis Services OLAP
provider, XML providers, SSIS (DTS) providers, PostgresSQL providers,
and even data replication providers. Figure 2 shows the entire list of providers available within the Linked Servers node of SQL Server Management Studio.
The following example adds an Oracle linked server called 'ORACLE_DATABASE' that connects to the database specified by the SQL*Net string 'my_sqlnet_connect_string':
EXEC sp_addlinkedserver @server='ORACLE_DATABASE',
@srvproduct='Oracle', @provider='MSDAORA',
@datasrc='my_sqlnet_connect_string'
The next example creates a linked server reference for an Access database called CustomersPlus.mdb. As you can see in Figure 3, this Microsoft Access database is an Access 2000 file format database.
The following example adds an Access database linked server entry called 'ACCESS_DATABASE_CUSTOMERS' that establishes a connection to the database 'CustomersPlus.mdb' stored in the C:\temp directory:
EXECUTE sp_addlinkedserver @server='ACCESS_DATABASE_CUSTOMERS',
@srvproduct='Access',
@provider='Microsoft.Jet.OLEDB.4.0',
The CustomersPlus.mdb
is available on the CD included with this book For this example, copy
this Access database file from the CD onto the same server machine on
which you have SQL Server installed. The Microsoft Access client
provider also needs to be present on this machine (which it will be you
have installed Microsoft Office on the system). You can now reference
this linked server directly from a SQL statement. sp_addlinkedserver
and all other SQL statements for this linked server set of examples are
also on the CD for this book in the script file LinkedServerSQL.sql. Here is a small sample of SQL code that selects all values from this Access database linked server entry:
SELECT CustomerID, ContactName, City, Country
FROM ACCESS_DATABASE_CUSTOMERS...SWCustomers
ORDER BY ContactName
Go
CustID ContactName City Country
------ ------------------ ---------- ---------------
PICCO Adam Greifer Los Angele USA
CHOPS Martin Sommer Berkeley USA
MEREP Thierry Gerardin Vannes FRANCE
BLAUS Juliana Bertucci Eugene USA
HANAR Yves Moison Paris FRANCE
(5 row(s) affected)
Note that you can see the fully qualified link server reference as the table name.
Here’s an example that adds a “SQL Server” linked server that resides on the 'DBARCH-LT2\SQL08DE01' machine:
EXECUTE sp_addlinkedserver @server='DBARCH-LT2\SQL08DE01',
@srvproduct='SQL Server'
Then you select data from a table on that linked server:
----------------------------------------------------
-- Selecting data from the Linked Server directly --
----------------------------------------------------
SELECT TOP 10
[CustomerID]
,[CustomerName]
,sum([YTDSalesTotal]) as 'YTD Sales'
FROM [DBARCH-LT2\SQL08DE01].[Unleashed].[dbo].[HotCustomerPlus]
GROUP BY [CustomerID]
,[CustomerName]
ORDER BY 3 desc
go
CustomerID CustomerName YTD Sales
----------- ---------------------------------------- -------------
85 Roadway Bicycle Supply 188509.608000
599 Westside Plaza 178835.169285
433 Thorough Parts and Repair Services 168182.664000
205 Rally Master Company Inc 146097.433161
546 Field Trip Store 135208.616867
193 Perfect Toys 134068.411416
697 Brakes and Gears 125784.511476
448 Action Bicycle Specialists 122380.103796
506 Great Bikes 122283.656936
230 Global Bike Retailers 115936.910796
(10 row(s) affected)
This example adds an Excel 8.0 spreadsheet as a linked server:
/* Set up of an Excel linked server */
EXEC sp_addlinkedserver
'ExcelSW', /* linked server name you want to use*/
'Jet Excel', /* product name – can be anything */
'Microsoft.Jet.OLEDB.4.0', /* OLE provider name */
'd:\SWCustomers.xls', /* datasource name */
NULL, /* location not needed in this case */
'Excel 8.0', /* Provider string if needed */
NULL /* catalog name if needed */
go
This example adds an ODBC data source as a linked server called 'ODBC_with_DATA_SOURCE'. The ODBC connection string must be registered on the local server to use this linked server:
EXEC sp_addlinkedserver
@server='ODBC_with_DATA_SOURCE',
@srvproduct='ODBC',
@provider='MSDASQL',
@datasrc='My_ODBC_connection_string'
This example adds an ODBC data source as a linked server called 'ODBC_with_PROVIDER_STRING'.
Unlike with the previous example, an ODBC data source does not need to
exist. The information normally stored as an ODBC data source is stored
in the provstr argument:
EXEC sp_addlinkedserver
@server='ODBC_with_PROVIDER_STRING',
@srvproduct='ODBC',
@provider='MSDASQL',
@provstr='DRIVER={SQL Server}; SERVER=MyServer; UID=sa;PWD=;'
Following is an example of a distributed query that accesses multiple tables via linked servers:
SELECT substring(CustomerID,1,5) as 'CustID',
substring(ContactName,1,18) as ContactName,
substring(City,1,10) as 'City',
substring(Country,1,15) as 'Country'
FROM [Linked ExcelSW]...[SWCustomers$]
UNION
SELECT substring(CustomerID,1,5) as 'CustID',
substring(ContactName,1,18) as ContactName,
substring(City,1,10) as 'City',
substring(Country,1,15) as 'Country'
FROM ACCESS_DATABASE_CUSTOMERS...SWCustomers
go
CustID ContactName City Country
------ ------------------ ---------- ---------------
BLAUS John Monroe Concord USA
BLAUS Juliana Bertucci Eugene USA
CHOPS Martin Sommer Berkeley USA
HANAR Yves Moison Paris FRANCE
MEREP Thierry Gerardin Vannes FRANCE
PICCO Adam Greifer Los Angele USA
(6 row(s) affected)
In
this example, you unite customers from the Access database with
customers from the Excel spreadsheet, all as a single SQL statement
within SQL Server.
sp_linkedservers
To see the linked servers defined within a SQL Server instance, you simply use sp_linkedservers:
The sp_linkedservers execution provides the list of all linked servers on this SQL Server:
SRV_NAME SRV_PROVIDERNAME SRV_PRODUCT SRV_DATASOURCE
------------------------- ----------------------- ---------- ---------------------
ACCESS_DATABASE_CUSTOMERS Microsoft.Jet.OLEDB.4.0 Access C:\temp\CustomersPlus.mdb
DBARCHLT\SQL08DE04 SQLNCLI SQL Server DBARCHLT\SQL08DE04
Linked ExcelSW Microsoft.Jet.OLEDB.4.0 Jet Excel
C:\TEMP\SWCustomers.xls
(3 row(s) affected)
Since the introduction of
SQL Server 2005, you can also get the same information via system views
set up for this purpose. In this case, you can query the system catalog
view sys.servers directly to get your information on linked servers:
select server_id,
substring(name,1,26) as 'name',
substring(product,1,10) as 'Product',
substring(provider,1,24) as 'Provider',
substring(data_source,1,25) as 'Source'
from sys.servers
order by server_id
go
id name Product Provider Source
---- -------------------------- ---------- ------------------------ --------------
0 DBARCHLT\SQL08DE04 SQL Server SQLNCLI DBARCHLT\SQL08DE04
3 ACCESS_DATABASE_CUSTOMERS Access –Microsoft.Jet.OLEDB C:\temp\
CustomersPlus.mdb
4 Linked ExcelSW Jet Excel –Microsoft.Jet.OLEDB C:\TEMP\
SWCustomers.xls
(3 row(s) affected)
sp_dropserver
To unregister linked servers, you can use sp_dropserver. Only members of the sysadmin and setupadmin fixed server roles can execute this stored procedure:
sp_dropserver [@server =] 'server' [, [@droplogins =] {'droplogins' | NULL}]
The elements of the syntax are as follows:
server— The linked server that will be unregistered.
droplogins—
An argument that specifies the logins associated with the server should
be dropped. If this argument is not specified, the server is dropped
only if logins do not exist for this linked server.
The following example unregisters Oracle, Access, and SQL Server databases:
EXECUTE sp_dropserver @server='ORACLE_DATABASE', @droplogins='droplogins'
EXECUTE sp_dropserver @server='ACCESS_DATABASE_CUSTOMERS'
EXECUTE sp_dropserver @server='DBARCH-LT2\SQL08DE01',@droplogins='droplogins'
sp_serveroption
You can configure linked servers by using sp_serveroption.
This affects how distributed queries behave at the linked server
provider level. In other words, the options you set with the
sp_serveroption
procedure are for a particular linked server entry only. Only users
with the sysadmin or setupadmin fixed server roles can run this
procedure, which has the following syntax:
sp_serveroption [[@server =] 'server']
[,[@optname =] 'option_name']
[,[@optvalue =] 'option_value']
The elements of the syntax are as follows:
server— The linked server affected by this option.
option_name— The name of the option to be configured. The valid option names follow:
Option Name | Description |
---|
'collation compatible' | If optvalue is set to TRUE, SQL Server assumes that the linked server has the same character set and collation sequence. Set this option to TRUE only if you are sure the character sets and collation are identical. |
'connect timeout' | The
length of time, in seconds, to wait before timing out the connection
attempt to the linked server. If set to 0, this option uses the
sp_configure default value. |
'data access' | If optvalue is set to TRUE
and if the OLE DB provider supports them, distributed queries are
allowed. If optvalue is set to FALSE, distributed queries are disabled
on this linked server. |
'lazy schema validation' | If optvalue is set to TRUE, the check of the schema for remote tables will be skipped at the beginning of the query. |
'query timeout' | Length of time, in seconds, to wait before timing out queries against linked server. If set to 0, this option uses the sp_configure default value. |
'rpc' | If the optvalue is set to TRUE, this option allows RPCs from the linked server. |
'rpc out' | If the optvalue is set to TRUE, this option allows RPCs to the linked server. |
'use remote collation' | If the optvalue is set to TRUE, this option uses the collation of remote columns for SQL Server data sources or the specified collation name for non–SQL Server sources. If set to FALSE, this option uses the local server default collation. |
'collation name' | If use remote collation is set to TRUE
and the linked server is not a SQL Server, this option specifies the
name of the collation to be used on the linked server. Use this option
when the OLE DB data source has a collation that matches one of the SQL
Server collations. |
option_value—
The value of this option. Valid values are TRUE (or ON) and FALSE (or
OFF), a non-negative integer for the connect timeout and query timeout
options, or a collation name for the collation name option.
The following example disables distributed queries to the ORACLE_DATABASE linked server:
EXECUTE sp_serveroption @server='ORACLE_DATABASE',
@optname='data access', @optvalue='FALSE'
The following example enables Remote Procedure Calls to the SQL_SERVER_DB linked server:
EXECUTE sp_serveroption @server='SQL_SERVER_DB',
@optname='rpc out', @optvalue='TRUE'
To set the query timeout to 60 seconds for the SQL Server data source, you execute the following command:
EXECUTE sp_serveroption 'DBARCH-LT2\SQL08DE01', 'query timeout', 60
To display the options currently enabled for a linked server, you use sp_helpserver:
EXECUTE sp_helpserver @server='DBARCH-LT2\SQL08DE01'
GO
name network_name status id connect..
------------------- ------------------- ------- -- ---------
DBARCH-LT2\SQL08DE01 DBARCHLT\SQL2005SUB rpc.. 0 0 60